package com.yunwaikeji.gy_tool_library.widget;

import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.animation.TranslateAnimation;
import android.widget.LinearLayout;
import android.widget.PopupWindow;

import com.yunwaikeji.gy_tool_library.R;
import com.yunwaikeji.gy_tool_library.info.GYPopupWindowInfo;
import com.yunwaikeji.gy_tool_library.interface1.GYViewBgInterface;
import com.yunwaikeji.gy_tool_library.interface1.GYViewGroupInterface;
import com.yunwaikeji.gy_tool_library.set.GYViewBgBuilder;
import com.yunwaikeji.gy_tool_library.set.GYViewGroupSetSet;
import com.yunwaikeji.gy_tool_library.utils.display.GYDisplayUtils;
import com.yunwaikeji.gy_tool_library.utils.GYNavigationBarUtils;
import com.yunwaikeji.gy_tool_library.utils.GYUtils;
import com.yunwaikeji.gy_tool_library.view.GYLinearLayout;

public class GYPopupWindow extends PopupWindow implements GYViewBgInterface<GYLinearLayout, GYPopupWindow.GYViewBgBuilder1>, GYViewGroupInterface<GYLinearLayout, GYPopupWindow.GYViewSet>, GYPopupWindowInfo {
    public Context context;
    private float bgAlpha = 0f;
    private float darkAlpha = 0.4f;
    private long showTime = 200;
    private long dismissTime = 200;
    private Location location = Location.CENTER;
    private Animation animation = Animation.NORMAL;
    private boolean isShowAnimation = true;//是否显示弹出动画
    private boolean isBackgroundAnimation = true;//是否显示背景变色动画
    private boolean cancelable = true;//点击返回是否可以关闭
    private boolean canceledOnTouchOutside = true;//点击外部是否可以关闭

    private int[] xyxy = {};

//    private int moveX = 0;
//    private int moveY = 0;

    private View outsideView;
    private LinearLayout gravityLL;
    private GYLinearLayout maxLL;
    private GYLinearLayout contentLL;

    public GYPopupWindow(Context context) {
        super(context);
        this.context = context;
        init();
    }

    private void init() {
        View view = LayoutInflater.from(context).inflate(R.layout.popup_window_gy, null);
        int bottom = 0;
        if (GYNavigationBarUtils.isShow(GYUtils.scanForActivity(context))) {
            bottom = GYNavigationBarUtils.getHeight(context);
        }
        view.setPadding(0, 0, 0, bottom);
        outsideView = view.findViewById(R.id.outsideView);
        gravityLL = view.findViewById(R.id.gravityLL);
        maxLL = view.findViewById(R.id.maxLL);
        contentLL = view.findViewById(R.id.contentLL);
        setContentView(view);
        // 用于PopupWindow的View
//        View contentView=LayoutInflater.from(context).inflate(layoutRes, null, false);
        // 创建PopupWindow对象，其中：
        // 第一个参数是用于PopupWindow中的View，第二个参数是PopupWindow的宽度，
        // 第三个参数是PopupWindow的高度，第四个参数指定PopupWindow能否获得焦点
        setWidth(WindowManager.LayoutParams.MATCH_PARENT);
        setHeight(WindowManager.LayoutParams.MATCH_PARENT);
        // 拦截点击穿透（获取焦点）
        setFocusable(true);
        // 设置PopupWindow的背景
        setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        // 设置PopupWindow是否能响应外部点击事件
        setOutsideTouchable(true);
        // 设置PopupWindow是否能响应点击事件
        setTouchable(true);
        // 显示PopupWindow，其中：
        // 第一个参数是PopupWindow的锚点，第二和第三个参数分别是PopupWindow相对锚点的x、y偏移
//        popupWindow.showAsDropDown(scrollView, 0, 0);
        //覆盖状态栏
        setClippingEnabled(false);
        setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
        setAnimationStyle(0);
        setTouchInterceptor(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_OUTSIDE && !isFocusable()) {
                    //如果焦点不在popupWindow上，且点击了外面，不再往下dispatch事件：
                    //不做任何响应,不 dismiss popupWindow
                    return true;
                }
                //否则default，往下dispatch事件:关掉popupWindow，
                return false;
            }
        });
        outsideView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (canceledOnTouchOutside) {
                    dismiss();
                }
            }
        });
//        outsideView.setOnKeyListener(new View.OnKeyListener() {
//            @Override
//            public boolean onKey(View view, int i, KeyEvent keyEvent) {
//                if (i == KeyEvent.KEYCODE_BACK && !cancelable) {
//                    return true;
//                }
//                return false;
//            }
//        });
        view.setFocusable(true);
        view.setFocusableInTouchMode(true);
        view.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View view, int i, KeyEvent keyEvent) {
                if (i == KeyEvent.KEYCODE_BACK && !cancelable) {
                    return true;
                }
                return false;
            }
        });

//        getViewSet().setMaxSizeProportion(1f, 1f);

        getViewSet().setLocation(location);
    }

    private boolean isShowing = false;

    @Override
    public void dismiss() {
        if (isShowing && !isClickDismiss) {
            isClickDismiss = true;
            if (!isShowAnimation && !isBackgroundAnimation) {
                isShowing = false;
                super.dismiss();
            } else {
                dismissAnimation();
                bgChangeToBright();
                handler.postDelayed(runnable, dismissTime);
            }
        }
    }

    private boolean isClickDismiss = false;
    private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            if (bgAlpha == 0f) {
                GYPopupWindow.super.dismiss();
                isShowing = false;
                isClickDismiss = false;
                handler.removeCallbacks(runnable);
            } else {
                handler.postDelayed(runnable, 0);
            }
        }
    };

    public void show() {
        show(contentLL);
    }

    public void show(View view) {
        if (!isShowing) {
            showAtLocation(view, 0, 0, 0);
            if (!isShowAnimation && !isBackgroundAnimation) {
                isShowing = true;
            } else {
                showAnimation();
                bgChangeToDark();
                handler.postDelayed(isDismissRunnable, showTime);
            }
        }
    }

    // 是否可以关闭
//    private boolean isShowDismiss = false;
    private Runnable isDismissRunnable = new Runnable() {
        @Override
        public void run() {
            isShowing = true;
        }
    };

    private void showAnimation() {
        if (!isShowAnimation) {
            return;
        }
        if (location == Location.WINDOW_LEFT_TOP
                || location == Location.WINDOW_LEFT_CENTER
                || location == Location.WINDOW_LEFT_BOTTOM) {
            animation(false, -1, 0, 0, 0);
        } else if (location == Location.WINDOW_TOP_LEFT
                || location == Location.WINDOW_TOP_CENTER
                || location == Location.WINDOW_TOP_RIGHT) {
            animation(false, 0, 0, -1, 0);
        } else if (location == Location.WINDOW_RIGHT_TOP
                || location == Location.WINDOW_RIGHT_CENTER
                || location == Location.WINDOW_RIGHT_BOTTOM) {
            animation(false, 1, 0, 0, 0);
        } else if (location == Location.WINDOW_BOTTOM_LEFT
                || location == Location.WINDOW_BOTTOM_CENTER
                || location == Location.WINDOW_BOTTOM_RIGHT) {
            animation(false, 0, 0, 1, 0);
        } else {
            animation(false, 0, 0, 0, 0);
        }
    }

    private void dismissAnimation() {
        if (!isShowAnimation) {
            return;
        }
        if (location == Location.WINDOW_LEFT_TOP
                || location == Location.WINDOW_LEFT_CENTER
                || location == Location.WINDOW_LEFT_BOTTOM) {
            animation(false, 0, -1, 0, 0);
        } else if (location == Location.WINDOW_TOP_LEFT
                || location == Location.WINDOW_TOP_CENTER
                || location == Location.WINDOW_TOP_RIGHT) {
            animation(false, 0, 0, 0, -1);
        } else if (location == Location.WINDOW_RIGHT_TOP
                || location == Location.WINDOW_RIGHT_CENTER
                || location == Location.WINDOW_RIGHT_BOTTOM) {
            animation(false, 0, 1, 0, 0);
        } else if (location == Location.WINDOW_BOTTOM_LEFT
                || location == Location.WINDOW_BOTTOM_CENTER
                || location == Location.WINDOW_BOTTOM_RIGHT) {
            animation(false, 0, 0, 0, 1);
        } else {
            animation(false, 0, 0, 0, 0);
        }
    }

    private void animation(boolean isShow, float fromXValue, float toXValue, float fromYValue, float toYValue) {
        TranslateAnimation translateAnimation = new TranslateAnimation(android.view.animation.Animation.RELATIVE_TO_SELF, fromXValue, android.view.animation.Animation.RELATIVE_TO_SELF, toXValue,
                android.view.animation.Animation.RELATIVE_TO_SELF, fromYValue, android.view.animation.Animation.RELATIVE_TO_SELF, toYValue);
        //执行后是否停留在执行后的位置
        translateAnimation.setFillAfter(true);
        //执行后是否停留在初始位置
//            translateAnimation.setFillBefore(false);
        //动画重复执行次数
//            translateAnimation.setRepeatCount(0);
        //动画执行前等待时间
//            translateAnimation.setStartOffset(0);
        //动画执行时间
        translateAnimation.setDuration(isShow ? showTime : dismissTime);
        contentLL.startAnimation(translateAnimation);
    }

//    public GYPopupWindow setGravity(int gravity) {
//        gravityLL.setGravity(gravity);
//        return this;
//    }

    //逐渐变暗
    private void bgChangeToDark() {
        handler.postDelayed(darkRunnable, 0);
    }

    //逐渐变亮
    private void bgChangeToBright() {
        handler.postDelayed(brightRunnable, 0);
    }

    private Runnable darkRunnable = new Runnable() {
        @Override
        public void run() {
            handler.removeCallbacks(brightRunnable);
            bgAlpha += 0.02f;
            if (isBackgroundAnimation) {
                bgAlpha += 0.02f;
                if (bgAlpha < darkAlpha) {
                    handler.postDelayed(darkRunnable, showTime / 20);
                } else {
                    handler.removeCallbacks(darkRunnable);
                    bgAlpha = darkAlpha;
                }
            } else {
                bgAlpha = darkAlpha;
                handler.removeCallbacks(darkRunnable);
            }
            getViewSet().setOutsideAlpha(bgAlpha);
        }
    };

    private Handler handler = new Handler();
    private Runnable brightRunnable = new Runnable() {
        @Override
        public void run() {
            handler.removeCallbacks(darkRunnable);
            bgAlpha -= 0.02f;
            if (isBackgroundAnimation) {
                bgAlpha -= 0.02f;
                if (bgAlpha > 0f) {
                    handler.postDelayed(brightRunnable, dismissTime / 20);
                } else {
                    handler.removeCallbacks(brightRunnable);
                    bgAlpha = 0f;
                }
            } else {
                bgAlpha = 0f;
                handler.removeCallbacks(brightRunnable);
            }
            getViewSet().setOutsideAlpha(bgAlpha);
        }
    };

    @Override
    public void initView(AttributeSet attributeSet) {
        getBackgroundBuilder(attributeSet).build();
    }

    @Override
    public GYViewBgBuilder1 setBackgroundBuilder(GYViewBgBuilder1 gyViewBgBuilder1) {
        viewBgBuilder1 = gyViewBgBuilder1;
        return viewBgBuilder1;
    }

    private GYViewBgBuilder1 viewBgBuilder1;

    @Override
    public GYViewBgBuilder1 getBackgroundBuilder() {
        return getBackgroundBuilder(null);
    }

    @Override
    public GYViewBgBuilder1 getBackgroundBuilder(AttributeSet attributeSet) {
        if (viewBgBuilder1 == null) {
            viewBgBuilder1 = new GYViewBgBuilder1(contentLL, attributeSet);
        }
        return viewBgBuilder1;
    }

    public class GYViewBgBuilder1 extends GYViewBgBuilder<GYLinearLayout, GYViewBgBuilder1> {
        public GYViewBgBuilder1(View view, AttributeSet attributeSet) {
            super(view, attributeSet);
        }

        public GYViewBgBuilder1(View view) {
            super(view);
        }

        public GYPopupWindow toPop() {
            return GYPopupWindow.this;
        }
    }

    private GYViewSet viewSet;

    @Override
    public GYViewSet getViewSet() {
        if (viewSet == null) {
            viewSet = new GYViewSet(contentLL);
        }
        return viewSet;
    }

    public class GYViewSet extends GYViewGroupSetSet<GYLinearLayout, GYViewSet> {
        public GYViewSet(View view) {
            super(view);
        }

        public GYViewSet setClippingEnabled(boolean enabled) {
            GYPopupWindow.this.setClippingEnabled(enabled);
            return this;
        }

        private void setOutsideAlpha(float alpha) {
            outsideView.setAlpha(alpha);
        }

        public GYViewSet setDarkAlpha(float darkAlpha) {
            GYPopupWindow.this.darkAlpha = darkAlpha;
            return this;
        }

        public GYViewSet setAnimation(Animation animation) {
            GYPopupWindow.this.animation = animation;
            return this;
        }

        public GYViewSet setOrientation(int orientation) {
            contentLL.setOrientation(orientation);
            return this;
        }

        public GYViewSet setLocation(Location location) {
            toPop().location = location;
            if (location == Location.CENTER) {
                gravityLL.setGravity(Gravity.CENTER);
                maxLL.setGravity(Gravity.CENTER);
            } else if (location == Location.WINDOW_LEFT_TOP) {
                gravityLL.setGravity(Gravity.LEFT | Gravity.TOP);
                maxLL.setGravity(Gravity.LEFT | Gravity.TOP);
            } else if (location == Location.WINDOW_LEFT_CENTER) {
                gravityLL.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
                maxLL.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
            } else if (location == Location.WINDOW_LEFT_BOTTOM) {
                gravityLL.setGravity(Gravity.LEFT | Gravity.BOTTOM);
                maxLL.setGravity(Gravity.LEFT | Gravity.BOTTOM);
            } else if (location == Location.WINDOW_TOP_LEFT) {
                gravityLL.setGravity(Gravity.TOP | Gravity.LEFT);
                maxLL.setGravity(Gravity.TOP | Gravity.LEFT);
            } else if (location == Location.WINDOW_TOP_CENTER) {
                gravityLL.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL);
                maxLL.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL);
            } else if (location == Location.WINDOW_TOP_RIGHT) {
                gravityLL.setGravity(Gravity.TOP | Gravity.RIGHT);
                maxLL.setGravity(Gravity.TOP | Gravity.RIGHT);
            } else if (location == Location.WINDOW_RIGHT_TOP) {
                gravityLL.setGravity(Gravity.RIGHT | Gravity.TOP);
                maxLL.setGravity(Gravity.RIGHT | Gravity.TOP);
            } else if (location == Location.WINDOW_RIGHT_CENTER) {
                gravityLL.setGravity(Gravity.RIGHT | Gravity.CENTER_VERTICAL);
                maxLL.setGravity(Gravity.RIGHT | Gravity.CENTER_VERTICAL);
            } else if (location == Location.WINDOW_RIGHT_BOTTOM) {
                gravityLL.setGravity(Gravity.RIGHT | Gravity.BOTTOM);
                maxLL.setGravity(Gravity.RIGHT | Gravity.BOTTOM);
            } else if (location == Location.WINDOW_BOTTOM_LEFT) {
                gravityLL.setGravity(Gravity.BOTTOM | Gravity.LEFT);
                maxLL.setGravity(Gravity.BOTTOM | Gravity.LEFT);
            } else if (location == Location.WINDOW_BOTTOM_CENTER) {
                gravityLL.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL);
                maxLL.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL);
            } else if (location == Location.WINDOW_BOTTOM_RIGHT) {
                gravityLL.setGravity(Gravity.BOTTOM | Gravity.RIGHT);
                maxLL.setGravity(Gravity.BOTTOM | Gravity.RIGHT);
            }
            return this;
        }

        public GYViewSet setWidthProportion(float widthProportion) {
            contentLL.getViewSet().setWidthPx(GYUtils.getWindowWidth(context, widthProportion));
            return this;
        }

        public GYViewSet setHeightProportion(float heightProportion) {
            contentLL.getViewSet().setHeightPx(GYUtils.getWindowHeight(context, heightProportion));
            return this;
        }

        public GYViewSet setSizeProportion(float widthProportion, float heightProportion) {
            contentLL.getViewSet().setSizePx(GYUtils.getWindowWidth(context, widthProportion), GYUtils.getWindowHeight(context, heightProportion));
            return this;
        }

        public GYViewSet setMaxWidthProportion(float maxWidthProportion) {
            maxLL.getViewSet().setWidthPx(GYUtils.getWindowWidth(context, maxWidthProportion));
            return this;
        }

        public GYViewSet setMaxHeightProportion(float maxHeightProportion) {
            maxLL.getViewSet().setHeightPx(GYUtils.getWindowHeight(context, maxHeightProportion));
            return this;
        }

        public GYViewSet setMaxSizeProportion(float maxWidthProportion, float maxHeightProportion) {
            maxLL.setLayoutParams(new LinearLayout.LayoutParams(GYUtils.getWindowWidth(context, maxWidthProportion), GYUtils.getWindowHeight(context, maxHeightProportion)));
            return this;
        }

        public GYViewSet setMaxWidthDp(int maxWidthDp) {
            maxLL.getViewSet().setWidthDp(maxWidthDp);
            return this;
        }

        public GYViewSet setMaxWidthPx(int maxWidthPx) {
            maxLL.getViewSet().setWidthPx(maxWidthPx);
            return this;
        }

        public GYViewSet setMaxHeightDp(int maxHeightDp) {
            maxLL.getViewSet().setHeightDp(maxHeightDp);
            return this;
        }

        public GYViewSet setMaxHeightPx(int maxHeightPx) {
            maxLL.getViewSet().setHeightPx(maxHeightPx);
            return this;
        }

        public GYViewSet setMaxSizeDp(int maxWidthDp, int maxHeightDp) {
            return setMaxSizePx(GYDisplayUtils.dp2px(context, maxWidthDp), GYDisplayUtils.dp2px(context, maxHeightDp));
        }

        public GYViewSet setMaxSizePx(int maxWidthPx, int maxHeightPx) {
            maxLL.getViewSet().setSizePx(maxWidthPx, maxHeightPx);
            return this;
        }

        public GYViewSet setBackgroundAnimation(boolean backgroundAnimation) {
            isBackgroundAnimation = backgroundAnimation;
            return this;
        }

        public GYViewSet setShowAnimation(boolean showAnimation) {
            isShowAnimation = showAnimation;
            return this;
        }

        public GYViewSet setDarkBgAlpha(float darkBgAlpha) {
            GYPopupWindow.this.darkAlpha = darkBgAlpha;
            return this;
        }

        public GYViewSet setShowTime(long showTime) {
            GYPopupWindow.this.showTime = showTime;
            return this;
        }

        public GYViewSet setDismissTime(long dismissTime) {
            GYPopupWindow.this.dismissTime = dismissTime;
            return this;
        }

        public GYViewSet setOutsideTouchable(boolean touchable) {
            GYPopupWindow.super.setOutsideTouchable(touchable);
            return this;
        }

        public GYViewSet setCancelable(boolean cancel) {
            cancelable = cancel;
            return this;
        }

        public GYViewSet setCanceledOnTouchOutside(boolean cancel) {
            canceledOnTouchOutside = cancel;
            return this;
        }

        public GYPopupWindow toPop() {
            return GYPopupWindow.this;
        }
    }

}
